package com.sleepcamel.rest.domain;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.sleepcamel.rest.domain.method.parameter.MethodParameter;
import com.sleepcamel.rest.domain.sourcegenerator.MethodSourceGenerator;
import com.sleepcamel.rest.domain.util.MiscUtils;

public class BaseMethod<MP extends MethodParameter> extends TreeNode implements IEncodable, IImportDependant, IProducer, IConsumer, ISourceCodeGenerable{

	private Boolean useDefaultName;
	private JavaClass returnType = new JavaClass("void");
	protected Set<String> interfaceImports = new HashSet<String>();
	protected Set<String> classImports = new HashSet<String>();
	
	protected List<String> produces = new ArrayList<String>();
	protected List<String> consumes = new ArrayList<String>();

	protected List<MP> parameters = new ArrayList<MP>();
	
	public BaseMethod() {
		setName("newMethod");
	}
	
	public Boolean getUseDefaultName() {
		return useDefaultName;
	}
	
	public void setUseDefaultName(Boolean useDefaultName) {
		this.useDefaultName = useDefaultName;
	}
	
	public JavaClass getReturnType() {
		return returnType;
	}
	
	public void setReturnType(JavaClass returnType) {
		this.returnType = returnType;
	}

	@Override
	public boolean isEncodable() {
		return false;
	}

	public List<String> getProduces() {
		return produces;
	}

	public List<String> getConsumes() {
		return consumes;
	}

	@Override
	public Set<String> getInterfaceImports() {
		addClassImport(interfaceImports, returnType);
		for(MP parameter:parameters){
			interfaceImports.addAll(parameter.getInterfaceImports());
		}
		return interfaceImports;
	}
	
	@Override
	public Set<String> getClassImports() {
		addClassImport(classImports, returnType);
		for(MP parameter:parameters){
			classImports.addAll(parameter.getInterfaceImports());
		}
		return classImports;
	}
	
	protected void addClassImport(Set<String> set, JavaClass clazz){
		if ( !clazz.isPrimitive() ){
			if ( clazz.isArray() ){
				addClassImport(set, clazz.getComponentType());
			}else{
				set.addAll(clazz.getClassImports());
			}
		}
	}

	public String getValidName() {
		return MiscUtils.getValidName(getName(),true);
	}

	public void setParameters(List<MP> parameters) {
		this.parameters = parameters;
	}
	
	public void addParameter(MP parameter) {
		parameters.add(parameter);
	}

	public List<MP> getParameters() {
		return parameters;
	}
	
	@Override
	public String toString() {
		MethodSourceGenerator methodSourceGenerator = new MethodSourceGenerator();
		methodSourceGenerator.setData(this);
		return methodSourceGenerator.generateInterfaceSource();
	}
}
